package web

import (
	"errors"
	"github.com/gin-contrib/sessions"
	"github.com/robin/webook/internal/domain"
	"github.com/robin/webook/internal/service"
	"log"
	"net/http"

	regexp "github.com/dlclark/regexp2"
	"github.com/gin-gonic/gin"
)

const (
	emailRegexPattern    = `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`
	passwordRegexPattern = `^(?=.*[A-Z])(?=.*[a-z])(?=.*[\W_])(?=.{8,}).*$`
)

type UserHandler struct {
	emailRegexExp    *regexp.Regexp
	passwordRegexExp *regexp.Regexp

	svc *service.UserService
}

func NewUserHander(svc *service.UserService) *UserHandler {
	return &UserHandler{
		emailRegexExp:    regexp.MustCompile(emailRegexPattern, regexp.None),
		passwordRegexExp: regexp.MustCompile(passwordRegexPattern, regexp.None),

		svc: svc,
	}
}

// RegisterRoutes 注册路由
func (u *UserHandler) RegisterRoutes(server *gin.Engine) {
	ug := server.Group("/users")
	{
		ug.POST("/signup", u.Signup)
		ug.POST("/login", u.Login)
		ug.PUT("/edit", u.Edit)
		ug.GET("/profile", u.Profile)
	}

	// api := server.Group("/api/v1")
	// {
	// 	api.GET("/users", u.Profile)
	// 	api.GET("/users/:id", controllers.GetUserByID)
	// 	api.POST("/users", controllers.CreateUser)
	// 	api.PUT("/users/:id", controllers.UpdateUser)
	// 	api.DELETE("/users/:id", controllers.DeleteUser)
	// }
}

// Signup
func (uh *UserHandler) Signup(ctx *gin.Context) {
	type SignUpReq struct {
		Email           string `json:"email"`
		Password        string `json:"password"`
		ConfirmPassword string `json:"confirmPassword"`
	}

	var req SignUpReq
	if err := ctx.Bind(&req); err != nil {
		return
	}

	log.Printf("SignUpReq: %+v\n", req)

	isEmail, err := uh.emailRegexExp.MatchString(req.Email)
	if err != nil {
		ctx.String(http.StatusBadRequest, "校验邮箱时发生系统错误")
		return
	}

	if !isEmail {
		ctx.String(http.StatusBadRequest, "邮箱不对")
		return
	}

	if req.Password != req.ConfirmPassword {
		ctx.String(http.StatusBadRequest, "两次密码不一致")
		return
	}

	isPassword, err := uh.passwordRegexExp.MatchString(req.Password)

	if err != nil {
		ctx.String(http.StatusBadRequest, "校验密码时发生系统错误")
	}

	if !isPassword {
		ctx.String(http.StatusBadRequest, "密码必须包含数字、特殊字符，并且长度不小于8位")
		return
	}

	err = uh.svc.Signup(ctx, domain.User{
		Email:    req.Email,
		Password: req.Password,
	})
	if err != nil {
		ctx.String(http.StatusOK, err.Error())

		return
	}

	ctx.String(http.StatusOK, "hello 注册成功")
}

func (uh *UserHandler) Login(ctx *gin.Context) {
	var req struct {
		Email    string `json:"email"`
		Password string `json:"password"`
	}

	if err := ctx.ShouldBind(&req); err != nil {
		return
	}

	user, err := uh.svc.Login(ctx, req.Email, req.Password)
	switch {
	case err == nil:
		// 校验成功，将登录状态保存到 session
		sess := sessions.Default(ctx)
		sess.Set("userId", user.Id)
		sess.Options(sessions.Options{
			// 15分钟
			MaxAge: 900,
		})
		err = sess.Save()
		if err != nil {
			ctx.String(http.StatusOK, "系统错误")
			return
		}

		ctx.String(http.StatusOK, "登录成功")
	case errors.Is(err, service.ErrInvalidUserOrPassword):
		ctx.String(http.StatusOK, "用户名或密码错误")
	default:
		ctx.String(http.StatusOK, "系统错误")
	}
}

func (uh *UserHandler) Edit(ctx *gin.Context) {
	ctx.String(http.StatusCreated, "编辑成功")
}

func (uh *UserHandler) Profile(ctx *gin.Context) {
	ctx.String(http.StatusOK, "profile 来了")
}
